<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="abc" class="def">
        这是一个div标签, 属性id为abc，属性class为def
        <!-- id必须是全局唯一的，用来js抓住它，更新里面的数据 -->
        <!-- def可以不是唯一的，用css来描述其样式 -->
        <!-- 这是一个注释，不会再网页中显示 -->
    </div>
    <a href="./001.html" class="abc">
        这是一个a标签，可以链接到001.html
    </a>
    <!-- style代表css -->
    <!--  .def是class为def的选择器 -->
    <!--  颜色为# red green blue 像素颜色值, 0123456789abcdef f为最亮，0为不亮  -->
    <style>
        .def {
            background-color: #ccc;
            color: gold;
        }
    </style>
    <script>
        // 1. 定义变量和常量
        let myBianliang = 0 // 定义一个变量
        const myChangliang = 1 //定义一个 常量
        // 2. 数据类型
        let myNumber = 1 // number
        let myNull = null
        let myString = "1"
        let myBoolean = myNumber === myString // false，因为类型不一样
        // 定义function的几种方法
        function myFunction0(a, b) {
            return a * b
        }
        let myFunction1 = function (a, b) {
            return a * b
        }
        let myFunction2 = (a, b) => a * b
        let myFunction3 = (a, b) => {
            return a * b
        }
        // 以上4种方法定义出来的函数是一样的
        let myFunction4 = () => {
            console.log("This is an functional method")
        }
        // 应以一个对象，用 {  键: 值 }
        let myObject = {
            message: "how are you",
            count: 2,
            // Object里面也可以有函数
            log0: function () {
                return () => this // 计算结果仍可以是一个函数
                // 箭头函数和function的区别就是:箭头函数里的this和外面的this是一样的
            },
            log1: function () {
                return this
            }
        }
        // 如果访问myObject中的某个值，可以
        let myTest0 = myObject["log0"]
        let myTest1 = myObject.log0
        console.log("两种方法结果应该一样", { myTest0, myTest1 })
        console.log({
            "1个括号": myObject.log1(), // 得出()=>this这个箭头函数
            "1个括号(函数)": myObject.log0(), // 得出()=>this这个箭头函数
            "两个括号": myObject.log0()(), // 得出()=>this 的计算结果
        })
        let myArray = ["niHao", 234, myObject, null] // 在Array里还可以嵌套对象或者任何其他变量
        // 访问myArray, 从0开始
        console.log("myArray的第1个元素:", myArray[1]) // 234
        // 修改myArray
        console.log("修改myArray之前", myArray)
        myArray[5] = "This is the 3rd element of myArray"
        console.log("修改myArray之后", myArray)
        console.log("-----------for循环--------")
        for (let i = 0; i < myArray.length; i++) {
            console.log("myArray第" + i + "个元素", myArray[i])
        }
        console.log("--------for in 循环-------")
        for (let i in myArray) {
            console.log("myArray第" + i + "个元素", myArray[i])
        }
        console.log("--------for of 循环-------")
        for (let item of myArray) {
            console.log("myArray元素", item)
        }
        console.log("--------if 语句-------")
        let test2 = [9, 100, 101]
        for (let score of test2) {
            if (score < 100) {
                console.log("分数<100:", score)
            } else if (score > 100) {
                console.log("分数>100:", score)
            } else {
                console.log("分数正好是100:", score)
            }
        }
        console.log("-------- while循环和break ------")
        let test3 = 0
        while (test3 < 3) {
            test3++
            console.log("while循环1 test3值为", test3)
        }
        console.log("-------- while (true)循环 ------")
        while (true) {
            // 会一直执行，直到break
            test3++
            if (test3 > 8) {
                console.log("---break---")
                console.log("在break时,test3=", test3)
                break
            }
        }
        myAsync() // 每过1秒console.log一个
        console.log("-------- try catch finally ------")
        try {
            const myConst = 0
            myConst = 1
        } catch (err) {
            console.log("出错了!", err)
        } finally {
            console.log("---finally---") // 无论出不出错都会运行
        }
        // 最难的 回调(callback) 和 异步
        console.log("-------- 回调(callback) 和 异步 ------")
        console.log(setTimeout, "setTimeout函数是一个javascript自带的函数，就像console.log,第一个参数应该是一个函数,第二个参数应该是一个number")
        console.log(setTimeout, "像这种，函数的参数是一个函数的语句，就叫函数回调")
        console.log(setTimeout, "当达到第2个参数所定义的毫秒数之后，会运行第一个参数所定义的函数")
        setTimeout(() => console.log("步骤 1.1"), 100)
        console.log("步骤 1.2")
        console.log("1.3 会发现运行的顺序并不是按JavaScript所写的那样")
        // 为了解决这个问题，所以出现了Promise对象
        // 语法为
        let myPromise = new Promise((resolve) => {
            setTimeout(() => {
                console.log("Promise 步骤2.1")
                resolve() //resolve代表Promise已解决，这时候会运行Promise对象的then
                // 由于回调的原因，如果return，只能return到回调函数内部
                // 但是resolve可以传到深层次中
            }, 200)
        })
        myPromise.then(() => { // then里也需要callback一个函数
            console.log("Promise 步骤2.2")
        })
        // 单问题是不能无限的then，所以出现了async 和await
        // async代表异步函数，await只能在异步函数里面使用
        async function myAsync() {
            for (let i = 0; i < 10; i++) {
                await new Promise((resolve) => {
                    setTimeout(() => {
                        console.log("过了" + i + "秒", i)
                        resolve()
                    }, 1000)
                })
            }
        }
    </script>
</body>

</html>